package com.cloudbroker.bcs.common.dao.base;

import com.alibaba.fastjson.JSONObject;
import com.cloudbroker.bcs.common.dao.exception.PojoStructureException;
import com.cloudbroker.bcs.common.entity.Markable;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;

public class MyBatisPojo implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 获取POJO对应的表名
     * 需要POJO中的属性定义@Table(name)
     * @return
     */
    public String tablename() {
        Table table = this.getClass().getAnnotation(Table.class);
        if(table != null)
            return table.name();
        else
            throw new PojoStructureException("undefine POJO @Table, need Tablename(@Table(name))");
    }

    /**
     * 获取POJO中的主键字段名
     * 需要定义@Id
     * @return
     */
    public String primaryKey() {
        for(Field field : this.getClass().getDeclaredFields()) {
            if(field.isAnnotationPresent(Id.class))
                return field.getName();
        }

        throw new RuntimeException("undefine POJO @Id");
    }

    public String primaryKeyValue() throws IllegalAccessException {
        for(Field field : this.getClass().getDeclaredFields()) {
            if(field.isAnnotationPresent(Id.class)) {
                field.setAccessible(true);
                return field.get(this) == null?null:field.get(this).toString();
            }
        }

        throw new RuntimeException("undefine POJO @Id");
    }
    /**
     * 用于存放POJO的列信息
     */
    private transient static Map<Class<? extends MyBatisPojo>,List<String>> columnMap = new HashMap<Class<? extends MyBatisPojo>, List<String>>();

    private boolean isNull(String fieldname) {
        try {
            Field field = this.getClass().getDeclaredField(fieldname);
            return isNull(field);
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }

        return false;
    }

    private boolean isNull(Field field) {
        try {
            field.setAccessible(true);
            return field.get(this) == null;
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        return false;
    }

    /**
     * 用于计算类定义
     * 需要POJO中的属性定义@Column(name)
     */
    public void caculationColumnList() {
        if(columnMap.containsKey(this.getClass()))
            return;

        Field[] fields = this.getClass().getDeclaredFields();
        List<String> columnList = new ArrayList<String>(fields.length);

        for(Field field : fields) {
            if(field.isAnnotationPresent(Column.class)||field.isAnnotationPresent(Id.class))
                columnList.add(field.getName());
        }

        columnMap.put(this.getClass(), columnList);
    }

    /**
     * 获取用于WHERE的 有值字段表
     * @return
     */
//    public List<WhereColumn> returnWhereColumnsName() {
//        Field[] fields = this.getClass().getDeclaredFields();
//        List<WhereColumn> columnList = new ArrayList<WhereColumn>(fields.length);
//
//        for(Field field : fields) {
//            if(field.isAnnotationPresent(Column.class) && !isNull(field))
//                columnList.add(new WhereColumn(field.getName(), field.getGenericType().equals(String.class)));
//        }
//
//        return columnList;
//    }

    /**
     * 获取用于WHERE的 有值字段表
     * @return
     */
    public String returnWhereColumns() throws IllegalAccessException {
        StringBuilder sb = new StringBuilder();
        Field[] fields = this.getClass().getDeclaredFields();
        int i = 0;
        for(Field field : fields) {
            if((field.isAnnotationPresent(Id.class)||field.isAnnotationPresent(Column.class)) && !isNull(field)) {
                if (i++ !=0)
                    sb.append(" and ");
                sb.append(field.getName() + "='" + field.get(this)+"'");

            }
        }
        return sb.toString();
    }
    /**
     * Where条件信息
     * @author HUYAO
     *
     */
    public class WhereColumn {
        public String name;
        public boolean isString;

        public WhereColumn(String name,boolean isString) {
            this.name = name;
            this.isString = isString;
        }
    }


    /**
     * 所有的字段累加
     * @return
     */
    public String returnAllColumnsName() {
        StringBuilder sb = new StringBuilder();

        List<String> list = columnMap.get(this.getClass());
        int i = 0;
        for(String column : list) {
            if(i++ != 0)
                sb.append(',');
            sb.append(column);
        }
        return sb.toString();
    }

    /**
     * 用于获取Insert的字段累加
     * @return
     */
    public String returnInsertColumnsName() {
        StringBuilder sb = new StringBuilder();

        List<String> list = columnMap.get(this.getClass());
        int i = 0;
        for(String column : list) {
            if(!column.equals(primaryKey())&&isNull(column))
                continue;

            if(i++ != 0)
                sb.append(',');
            sb.append(column);
        }
        return sb.toString();
    }

    /**
     * 用于获取Insert的字段映射累加
     * @return
     */
    public String returnInsertColumnsDefine() throws NoSuchFieldException, IllegalAccessException {
        StringBuilder sb = new StringBuilder();

        List<String> list = columnMap.get(this.getClass());
        int i = 0;
        for(String column : list) {
            if (!column.equals(primaryKey()) && isNull(column))
                continue;

            if (i++ != 0)
                sb.append(',');
            Field field = this.getClass().getDeclaredField(column);
            field.setAccessible(true);
            //primarykey 需要特殊处理
            if (column.equals(primaryKey())) {
                Method mycat_flag = null;
                boolean flag = false;
                try {
                    mycat_flag = this.getClass().getMethod("isMycat_flag");
                    flag = (boolean) mycat_flag.invoke(this);
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
                if (primaryKeyValue()!=null && !"".equals(primaryKeyValue())){
                    sb.append(primaryKeyValue());
                } else if (mycat_flag != null && flag){
                    sb.append("NEXT VALUE FOR MYCATSEQ_"+tablename().toUpperCase());
                }else {
                    sb.append("null");
                }
            } else {
                sb.append("'" + field.get(this).toString() + "'");

            }
        }
        return sb.toString();
    }

    /**
     * 用于获取Update Set的字段累加
     * @return
     */
    public String returnUpdateSet() throws NoSuchFieldException, IllegalAccessException {
        StringBuilder sb = new StringBuilder();

        List<String> list = columnMap.get(this.getClass());
        int i = 0;
        for(String column : list) {
            //不更新company_id
            if(isNull(column)||"company_id".equals(column))
                continue;

            if(i++ != 0)
                sb.append(',');
            Field field = this.getClass().getDeclaredField(column);
            field.setAccessible(true);
            sb.append(column).append("='"+field.get(this)+"'");
        }
        return sb.toString();
    }


    /**
     * 转化POJO为JSON格式
     * 需要org.json包支持,可以在json官网下载源码,或自己实现json编码
     * @return
     */
    public String toJSONString() {
        return JSONObject.toJSONString(this);
    }

    /**
     * 打印类字段信息
     */
    @Override
    public String toString() {
        Field[] fields = this.getClass().getDeclaredFields();
        StringBuilder sb = new StringBuilder();
        sb.append('[');
        for(Field f : fields) {
            if(Modifier.isStatic(f.getModifiers()) || Modifier.isFinal(f.getModifiers()))
                continue;
            Object value = null;
            try {
                f.setAccessible(true);
                value = f.get(this);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            if(value != null)
                sb.append(f.getName()).append('=').append(value).append(',');
        }
        sb.append(']');

        return sb.toString();
    }
}